using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TagTool.Devices;
using TagTool.Devices.Midi;
using System.Threading;

namespace TagTool.MidiTest
{
    public partial class FormMain : Form
    {
        MidiManager manager;
        MidiInputDevice midi = new MidiInputDevice(1);

        public FormMain()
        {
            InitializeComponent();
            
            manager = new MidiManager();

            int numOfInDevices = manager.NumOfInDevices;
            midiBox.Items.Add(string.Format("Number of midi input devices: {0}", numOfInDevices));
   
            for (int i = 0; i < numOfInDevices; i++)
            {
            }

            for (int i = 0; i < numOfInDevices; i++)
            {
                ToolStripMenuItem menuItem = new ToolStripMenuItem(string.Format("Device nr. {0}", i + 1), null, new EventHandler(OnMidiInputOpen));
                menuItem.Tag = i;
                openMidiInput.DropDownItems.AddRange(
                    new ToolStripItem [] {
                        menuItem
                    }
                );
            }          
            midiBox.ContextMenuStrip = contextMenu;

            //midi.ChannelVoiceEvent += new ChannelVoiceEventHandler(OnChannelVoiceEvent);
            midi.NoteOffEvent += new NoteOffEventHandler(OnNoteOffEvent);
            midi.NoteOnEvent += new NoteOnEventHandler(OnNoteOnEvent);
            midi.PolyphonicPressureEvent += new PolyphonicPressureEventHandler(OnKeyPressureEvent);
            midi.ProgramChangeEvent += new ProgramChangeEventHandler(OnProgramChangeEvent);
            midi.ControlChangeEvent += new ControlChangeEventHandler(OnControlChangeEvent);
            midi.ChannelPressureEvent += new ChannelPressureEventHandler(OnChannelPressureEvent);
            midi.PitchWheelEvent += new PitchWheelEventHandler(OnPitchWheelEvent);
            midi.ModeControlEvent += new ModeControlEventHandler(OnModeControlEvent);    
        }

        public void OnMidiInputOpen(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = (ToolStripMenuItem)(sender);
            if (menuItem.Tag != null)
            {
                uint id = Convert.ToUInt32(menuItem.Tag);
                midi.Connect();
                midiBox.Items.Add(string.Format("Result of connect: {0}", midi.Connected));
            }
        }

        private void closeMidiInput_Click(object sender, EventArgs e)
        {
            midi.Disconnect();
            midiBox.Items.Add(string.Format("Result of disconnect: {0}", midi.Connected));
        }

        private void OnChannelVoiceEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new ChannelVoiceEventHandler(ParseChannelVoiceMessage), sender, e);
        }

        private void OnNoteOffEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new NoteOffEventHandler(ParseNoteOffMessage), sender, e);
        }

        private void OnNoteOnEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new NoteOnEventHandler(ParseNoteOnMessage), sender, e);
        }

        private void OnKeyPressureEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new PolyphonicPressureEventHandler(ParseKeyPressureMessage), sender, e);
        }

        private void OnProgramChangeEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new ProgramChangeEventHandler(ParseProgramChangeMessage), sender, e);
        }

        private void OnControlChangeEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new ControlChangeEventHandler(ParseControlChangeMessage), sender, e);
        }

        private void OnChannelPressureEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new ChannelPressureEventHandler(ParseChannelPressureMessage), sender, e);
        }

        private void OnPitchWheelEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new PitchWheelEventHandler(ParsePitchWheelMessage), sender, e);
        }

        private void OnModeControlEvent(object sender, MidiDeviceEventArgs e)
        {
            Invoke(new ModeControlEventHandler(ParseModeControlMessage), sender, e);
        }

        private void ParseChannelVoiceMessage(object sender, MidiDeviceEventArgs e)
        {
            ChannelVoiceMessage msg = (ChannelVoiceMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Voice: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Data byte one: {0}, Data byte two: {1}", msg.DataByteOne, msg.DataByteTwo));
            UpdateListBox();
        }

        private void ParseNoteOffMessage(object sender, MidiDeviceEventArgs e)
        {
            NoteOffMessage msg = (NoteOffMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("NoteOff: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Note: {0}", msg.Note));
            UpdateListBox();
        }

        private void ParseNoteOnMessage(object sender, MidiDeviceEventArgs e)
        {
            NoteOnMessage msg = (NoteOnMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("NoteOn: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Note: {0}, Velocity: {1}", msg.Note, msg.Velocity));
            UpdateListBox();
        }

        private void ParseKeyPressureMessage(object sender, MidiDeviceEventArgs e)
        {
            PolyphonicPressureMessage msg = (PolyphonicPressureMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Key Pressure: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Pitch: {0}, Pressure: {1}", msg.Pitch, msg.Pressure));
            UpdateListBox();
        }

        private void ParseControlChangeMessage(object sender, MidiDeviceEventArgs e)
        {
            ControlChangeMessage msg = (ControlChangeMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Control Change: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Controller: {0}, Value: {1}", (MidiControllerType)msg.Controller, msg.Value));
            UpdateListBox();
        }

        private void ParseProgramChangeMessage(object sender, MidiDeviceEventArgs e)
        {
            ProgramChangeMessage msg = (ProgramChangeMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Program Change: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Program: {0}", msg.Program));
            UpdateListBox();
        }

        private void ParseChannelPressureMessage(object sender, MidiDeviceEventArgs e)
        {
            ChannelPressureMessage msg = (ChannelPressureMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Channel Pressure: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Pressure: {0}", msg.Pressure));
            UpdateListBox();
        }

        private void ParsePitchWheelMessage(object sender, MidiDeviceEventArgs e)
        {
            PitchWheelMessage msg = (PitchWheelMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Pitch Wheel: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Controller: {0}, Value: {1}", msg.Controller, msg.Value));
            UpdateListBox();
        }

        private void ParseModeControlMessage(object sender, MidiDeviceEventArgs e)
        {
            ModeControlMessage msg = (ModeControlMessage)e.ChannelMessage;
            midiBox.Items.Add(string.Format("Mode Control: {0}, Channel: {1}, TimeStamp: {2}", (MidiMessageStatus)msg.Status, msg.Channel, msg.TimeStamp));
            midiBox.Items.Add(string.Format("Mode: {0}, Value: {1}", msg.Mode, msg.Value));
            UpdateListBox();
        }

        private void getDeviceCaps_Click(object sender, EventArgs e)
        {
        }

        private void UpdateListBox()
        {
            midiBox.TopIndex = midiBox.Items.Count - 1;
        }
    }
}
